<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
<style>
html {
  font-family: Ahem;
  font-size: 10px;
}
#testArea {
  height: 6000px;
  width: 500px;
  background: red;
}
#target {
  position: fixed;
  left: 10px;
  top: 10px;
  width: 40px;
  height: 40px;
  background: yellow;
}
#frame {
  display: block;
  width: 100px;
  height: 100px;
}
</style>
<div id=testArea>
  <div id=target></div>
<br>
<br>
<br>
<iframe id=frame srcdoc='<div id="innerContent" style="width: 75px; height: 50px; background: blue"><input></input<div>'></iframe>
</div>
<p id="description"></p>
<div id="console"></div>
<script src="../../resources/js-test.js"></script>
<script>

setPrintTestResultsLazily();
if (window.internals)
    internals.settings.setViewportEnabled(true);

description("Ensure hit test cache works in correct scenarios of scrolling, dom and style changes.");

function hitTestCountDelta()
{
    var lastCount = 0;
    if ('lastHitTestCount' in document)
      lastCount = document.lastHitTestCount;
    var newCount = internals.hitTestCount(document);
    document.lastHitTestCount = newCount;
    return newCount - lastCount;
}

function hitTestCacheHitsDelta()
{
    var lastCount = 0;
    if ('lastHitTestCacheHits' in document)
      lastCount = document.lastHitTestCacheHits;
    var newCount = internals.hitTestCacheHits(document);
    document.lastHitTestCacheHits = newCount;
    return newCount - lastCount;
}

function clearCounts()
{
    internals.clearHitTestCache(document);
    document.lastHitTestCount = internals.hitTestCount(document);
    document.lastHitTestCacheHits = internals.hitTestCacheHits(document);
}

function checkElementAt(x, y, expectedHitTestCount, expectedHitTestCacheCount)
{
    shouldBe("document.elementFromPoint(" + x + "," + y + ")",
             "internals.clearHitTestCache(document); internals.elementFromPoint(document, " + x + ", " + y + ", false, false)");
    shouldBeEqualToNumber("hitTestCountDelta()", expectedHitTestCount);
    shouldBeEqualToNumber("hitTestCacheHitsDelta()", expectedHitTestCacheCount);
}

function checkChildFrameElementAt(x, y)
{
    shouldBe("internals.elementFromPoint(document, " + x + ", " + y + ", false, true)",
             "internals.clearHitTestCache(document); internals.elementFromPoint(document, " + x + ", " + y + ", false, true)");
}

onload = function() {
    clearCounts();
    debug('Hit test main div');
    debug('---------------------');

    // Verify that the cache is working; the second call
    // to checkElementAt should end up using the cache from the first call.
    checkElementAt(60, 60, 2, 0);
    checkElementAt(60, 60, 2, 1);

    debug('');
    debug('Hit test fixed div after scroll');
    debug('---------------------');

    // Verify that after scroll the hit cache isn't used but the
    // correct element is returned for the fixed position elements.
    document.lastHitNode = document.elementFromPoint(12, 12);
    clearCounts();
    checkElementAt(12, 12, 2, 0);
    window.scrollTo(0,  50);
    checkElementAt(12, 12, 2, 0);
    shouldBe("document.lastHitNode", "document.elementFromPoint(12, 12)");

    debug('');
    debug('Hit test after main frame scroll');
    debug('---------------------');

    // Verify that after scroll the hit cache isn't used but
    // the same element is returned for the adjusted co-ordinate.
    window.scrollTo(0, 0);
    document.lastHitNode = document.elementFromPoint(60, 75);
    clearCounts();
    checkElementAt(60, 75, 2, 0);
    window.scrollTo(0, 50);
    checkElementAt(60, 25, 2, 0);
    shouldBe("document.lastHitNode", "document.elementFromPoint(60, 25)");

    clearCounts();
    debug('');
    debug('Hit test after style change');
    debug('---------------------');
    checkElementAt(12, 12, 2, 0);
    document.getElementById('target').style.background = "blue";
    checkElementAt(12, 12, 2, 0);

    clearCounts();
    debug('');
    debug('Hit test after dom manipulation');
    debug('---------------------');
    checkElementAt(12, 12, 2, 0);
    document.getElementById('target').setAttribute("foo", "bar");
    checkElementAt(12, 12, 2, 0);

    clearCounts();
    document.getElementById('target').style.display = "none";
    window.scrollTo(0, 0);
    debug('');
    debug('Hit test iframe; ensuring child co-ordinates are not in parent cache');
    debug('---------------------');
    checkChildFrameElementAt(25, 80);
    checkChildFrameElementAt(15, 40);

    finishJSTest();
}
</script>
